/* 
 * Copyright 2009 Shared Object (www.sharedobject.ch)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package edos.prm.project;

import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import edos.prm.actor.Actor;
import edos.prm.artifact.Artifact;
import edos.prm.artifact.ArtifactSet;
import edos.prm.artifact.Attribute;
import edos.prm.engine.PrmSecurityManager;

/**
 * A Project is the global activity for which a process runs.
 * <p>
 * A project can represent an organization, a company, an open-source
 * development project - anything that has a purpose that necessitates the
 * definition of processes, the allocation of roles, the contribution of
 * actors and the measurement of progress via metrics.
 * 
 * @version 1.0
 */
public interface Project extends Artifact {
	
	/**
	 * The {@code ROOT_PROJECT} is the default project created on system
	 * start-up. It encapsulates all projects created.
	 */
	public static final Project ROOT_PROJECT = 
		new PrmProject("ROOT", "Default Project");
	
	/**
	 * Returns the name of the Project
	 * 
	 * @return the String name of the Project
	 */
	@Attribute
	public String getName();
	
	/**
	 * Returns the description of the Project
	 * 
	 * @return the Text form of the description of the Project
	 */
	@Attribute
	public String getDescription();
	
	/**
	 * Returns the URL of the Project
	 * 
	 * @return the URL of the Project
	 */
	@Attribute
	public URL getURL();

	/**
	 * Returns the Topics explored within the Project
	 * 
	 * @return a copy of the set of Topics explored within the Project
	 */
	@Attribute
	public Set<Topic> getTopics();

	/**
	 * Returns contact Actors for the Project
	 * 
	 * @return a copy of the set of contact Actors for the Project
	 */
	@Attribute
	public Set<Actor> getContacts();
	
	/**
	 * Gives the name of the parent project of the current project.
	 * 
	 * @return the parent of this project.
	 */
	public Project getParentProject();
	
	/**
	 * Return the list of children projects of this project
	 * 
	 * @return a copy of the set of children projects
	 */
	public Set<Project> getChildrenProjects();
	
	/**
	 * A default Java implementation of {@code Project}.
	 */
	public static final class PrmProject implements Project {

		private ArtifactSet<Project> children;
		private ArtifactSet<Actor> contacts;
		private HashSet<Topic> topics;
		private Project parent;
		private URL url;
		private String name;
		private String description;
		
		PrmProject(String name, String description, String...topicnames) {
			this.name = name;
			this.topics = new HashSet<Topic>();
			for ( String tname : topicnames ) {
				Topic topic = new Topic(tname, this);
				topics.add(topic);
			}
			this.description = description;
		}

		public void addChildProject(Project child) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ProjectManager.class, this.getClass());
			this.children.add(child);
		}

		public void addContact(Actor contact) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ProjectManager.class, this.getClass());
			this.contacts.add(contact);
		}

		public void addTopic(Topic topic) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ProjectManager.class, this.getClass());
			this.topics.add(topic);
		}

		public void setDescription(String description) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ProjectManager.class, this.getClass());
			this.description = description;
		}

		public void setUrl(URL url) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ProjectManager.class, this.getClass());
			this.url = url;
		}

		public Set<Project> getChildrenProjects() {
			HashSet<Project> result = new HashSet<Project>();
			result.addAll(children.getContents());
			return result;
		}

		public Set<Actor> getContacts() {
			HashSet<Actor> result = new HashSet<Actor>();
			result.addAll(contacts.getContents());
			return result;
		}

		public String getDescription() {
			return this.description;
		}

		public String getName() {
			return this.name;
		}

		public Project getParentProject() {
			return this.parent;
		}

		public Set<Topic> getTopics() {
			HashSet<Topic> result = new HashSet<Topic>();
			result.addAll(topics);
			return result;
		}

		public URL getURL() {
			return this.url;
		}
	}
}
